package com.htdu87.vnlicenceplatedetection;

import java.io.ByteArrayOutputStream;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.googlecode.tesseract.android.TessBaseAPI;

public class ScanActivity extends Activity implements Camera.PreviewCallback, Camera.AutoFocusCallback {
	private final String TAG = "htdu87 debug";
	private Camera mCamera;
	private CamPreview mPreview;
	private FrameLayout layPreview;
	private ViewFinder viewFinder;
	private Point screenSize;
	private Rect rec1, rec2, rec3, rec4;
	private String dataPath;
	private TessBaseAPI tessAPI;
	private boolean isDetecting;
	private Handler hanDetect;
	private Size previewSize;
	private ImageView imgPreview;
	private TextView lblResultText;
	private int count;
	private byte[] imgData;
	private Paint mPaint;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_scan);
		
		hanDetect = new Handler();
		isDetecting = false;
		count = 0;
		tessAPI = initTessAPI();
		
		screenSize = new Point();
		WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
		Display display = wm.getDefaultDisplay();
		display.getSize(screenSize);
		
		rec1 = new Rect(0, 0, screenSize.x/2, screenSize.y/2);
		rec2 = new Rect(screenSize.x/2, 0, screenSize.x, screenSize.y/2);
		rec3 = new Rect(0, screenSize.y/2, screenSize.x/2, screenSize.y);
		rec4 = new Rect(screenSize.x/2, screenSize.y/2, screenSize.x, screenSize.y);
		
		imgPreview = (ImageView)findViewById(R.id.img_preview);
		lblResultText = (TextView)findViewById(R.id.lbl_result_text);
		viewFinder = (ViewFinder)findViewById(R.id.view_finder);
		
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mPaint.setAlpha(0xFF);
		mPaint.setColor(0xFF00CCFF);
		mPaint.setStyle(Style.STROKE);
		mPaint.setStrokeWidth(2);

		if(checkCameraHardware()){
			mCamera = getCameraInstance();
			if(mCamera != null){
				mCamera.setPreviewCallback(this);
				mPreview = new CamPreview(this, mCamera);
				previewSize = mPreview.getPreviewSize();
				layPreview = (FrameLayout)findViewById(R.id.lay_preview);
				layPreview.addView(mPreview);
			}
			else{
				Log.d(TAG, "Can not access to camera");
			}
		}
		else{
			Log.d(TAG, "Camera not found");
		}
	}

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		mCamera = null;
		layPreview.removeView(mPreview);
		tessAPI.end();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		if(mCamera == null){
			mCamera = Camera.open();
			mPreview = new CamPreview(this, mCamera);
			layPreview.addView(mPreview);
			tessAPI = initTessAPI();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch(event.getAction()){
		case MotionEvent.ACTION_MOVE:
			float curX = event.getX();
			float curY = event.getY();
			
			int h = 150, w = 150;
			Rect r = viewFinder.getRectFinder();
			int pos = detectPos((int)curX, (int)curY);

			switch(pos){
			case 1:
				h = (int) (viewFinder.getRectHeight()+(r.top - curY));
				w = (int) (viewFinder.getRectWidth() +(r.left - curX));
				break;
			case 2:
				h = (int) (viewFinder.getRectHeight()+(r.top - curY));
				w = (int) (viewFinder.getRectWidth() +(curX - r.right));
				break;
			case 3:
				h = (int) (viewFinder.getRectHeight()+(curY - r.bottom));
				w = (int) (viewFinder.getRectWidth() +(r.left - curX));
				break;
			case 4:
				h = (int) (viewFinder.getRectHeight()+(curY - r.bottom));
				w = (int) (viewFinder.getRectWidth() +(curX - r.right));
				break;
			}
			
			viewFinder.setRectHeight(h<50?50:h);
			viewFinder.setRectWidth(w<50?50:w);
			viewFinder.refreshView();
			return true;
		default:
			return super.onTouchEvent(event);
		}
	}

	/** Check if this device has a camera */
	private boolean checkCameraHardware() {
	    if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
	        // this device has a camera
	        return true;
	    } else {
	        // no camera on this device
	        return false;
	    }
	}
	
	/** A safe way to get an instance of the Camera object. */
	private Camera getCameraInstance(){
	    Camera c = null;
	    try {
	        c = Camera.open(); // attempt to get a Camera instance
	    }
	    catch (Exception e){
	        // Camera is not available (in use or does not exist)
	    }
	    return c; // returns null if camera is unavailable
	}
	
	private int detectPos(int x, int y){
		if(rec1.contains(x, y))
			return 1;
		if(rec2.contains(x, y))
			return 2;
		if(rec3.contains(x, y))
			return 3;
		if(rec4.contains(x, y))
			return 4;
		return -1;
	}

	private TessBaseAPI initTessAPI(){
		String sdcardState = Environment.getExternalStorageState();
		if(sdcardState.equals(Environment.MEDIA_MOUNTED)){
			dataPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/com.htdu87.vnlicenceplatedetection";
			TessBaseAPI api = new TessBaseAPI();
			api.setDebug(false);
			api.setPageSegMode(TessBaseAPI.PageSegMode.PSM_AUTO_ONLY);
			api.init(dataPath, "eng", TessBaseAPI.OEM_TESSERACT_ONLY);
			return api;
		}
		Toast.makeText(this, "SD card not ready", Toast.LENGTH_SHORT).show();
		return null;
	}
	
	@Override
	public void onPreviewFrame(byte[] data, Camera camera) {
		// TODO Auto-generated method stub
		imgData = data;
		if(count == 0)
			mCamera.autoFocus(this);
		count++;
		if(count == 50)
			count = 0;
	}

	@Override
	public void onAutoFocus(boolean success, Camera camera) {
		// TODO Auto-generated method stub
		
	}
	
	public void btnDetect_Click(View v){
		if(!isDetecting){
			mCamera.stopPreview();
			mCamera.setPreviewCallback(null);
			hanDetect.post(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					int rw = viewFinder.getRectWidth();
					int rh = viewFinder.getRectHeight();
					Rect imgRect = new Rect(viewFinder.getPaddingLeft(), 0, previewSize.width, previewSize.height);
					ByteArrayOutputStream outstr = new ByteArrayOutputStream();
					YuvImage yuvimage = new YuvImage(imgData, ImageFormat.NV21, previewSize.width, previewSize.height, null);
					yuvimage.compressToJpeg(imgRect, 80, outstr);
					Bitmap bitmap = BitmapFactory.decodeByteArray(outstr.toByteArray() , 0, outstr.size());
					bitmap = Bitmap.createBitmap(bitmap, (bitmap.getWidth()/2)-(rw/2), (bitmap.getHeight()/2)-(rh/2), rw, rh);
					//bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
					
					tessAPI.setImage(bitmap);
					String regText = tessAPI.getUTF8Text();
					
					Canvas c = new Canvas(bitmap);
					for(Rect r : tessAPI.getWords().getBoxRects()){
						c.drawRect(r, mPaint);
					}
					imgPreview.setImageBitmap(bitmap);
					if(regText != null)
						lblResultText.setText(regText);
				}
			});
		}
		else{
			mCamera.setPreviewCallback(this);
			mCamera.startPreview();
		}
		isDetecting = !isDetecting;
	}
}
